package com.atguigu.guli.service.ucenter.service.impl;

import com.atguigu.common_utils.consts.SmsConsts;
import com.atguigu.common_utils.utils.FormUtils;
import com.atguigu.common_utils.utils.HttpClientUtils;
import com.atguigu.common_utils.utils.MD5;
import com.atguigu.guli.service.base.dto.MemberDto;
import com.atguigu.guli.service.base.exception.GuliException;
import com.atguigu.guli.service.base.result.ResultCodeEnum;
import com.atguigu.guli.service.base.utils.JwtHelper;
import com.atguigu.guli.service.base.utils.JwtInfo;
import com.atguigu.guli.service.ucenter.entity.Member;
import com.atguigu.guli.service.ucenter.entity.form.MemberRegistForm;
import com.atguigu.guli.service.ucenter.mapper.MemberMapper;
import com.atguigu.guli.service.ucenter.properties.WxProperties;
import com.atguigu.guli.service.ucenter.service.MemberService;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import org.apache.commons.lang.StringUtils;
import org.bouncycastle.math.raw.Mod;
import org.joda.time.format.FormatUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.Normalizer;
import java.util.Map;
import java.util.UUID;

/**
 * <p>
 * 会员表 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2021-08-09
 */
@Service
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements MemberService {
    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    WxProperties wxProperties;
    @Override
    public void regist(MemberRegistForm member) {
        String mobile = member.getMobile();
        //1、检查参数格式是否正确
        String code = member.getCode();
        //String mobile = member.getMobile();
        String nickname = member.getNickname();
        String password = member.getPassword();
        if(StringUtils.isEmpty(code)||
                StringUtils.isEmpty(mobile)||
                StringUtils.isEmpty(nickname)||
                StringUtils.isEmpty(password)||
                !FormUtils.isMobile(mobile)
        ){
            throw  new GuliException(ResultCodeEnum.PARAM_ERROR,new RuntimeException(ResultCodeEnum.PARAM_ERROR.getMessage()));
        }
        //校验手机号是否正确
        boolean mobile1 = FormUtils.isMobile(mobile);
        if (!mobile1){
            throw new GuliException(ResultCodeEnum.LOGIN_PHONE_ERROR,
                       new RuntimeException(ResultCodeEnum.LOGIN_PHONE_ERROR.getMessage()));
        }
        //判断手机号是否被注册
        LambdaQueryWrapper<Member> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Member::getMobile, mobile);
        Integer integer = this.baseMapper.selectCount(queryWrapper);
        if (integer>0){
            throw new GuliException(ResultCodeEnum.REGISTER_MOBLE_ERROR,
                    new RuntimeException(ResultCodeEnum.REGISTER_MOBLE_ERROR.getMessage()));
        }
        //校验验证码是否正确
        Object o = redisTemplate.opsForValue().get(SmsConsts.MOBILE_CODE_PREFIX + mobile);
        if(o==null&&!code.equals(o.toString())){
            throw new GuliException(ResultCodeEnum.CODE_ERROR,
                    new RuntimeException(ResultCodeEnum.CODE_ERROR.getMessage()));
        }
        //保存到数据库中
        Member member1 = new Member();
        BeanUtils.copyProperties(member,member1);
        member1.setPassword(MD5.encrypt(password));
        this.baseMapper.insert(member1);
        //删除redis缓存中的验证码
        redisTemplate.delete(SmsConsts.MOBILE_CODE_PREFIX+mobile);
    }

    /*
    登录验证
     */
    @Override
    public String login(String mobile, String password) {
        //根据手机号查询数据库
        LambdaQueryWrapper<Member> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Member::getMobile,mobile);
        Member member = this.baseMapper.selectOne(queryWrapper);
        if (member==null){
            new GuliException(ResultCodeEnum.LOGIN_PHONE_ERROR);
        }
        String password1 = member.getPassword();
        if (!MD5.encrypt(password).equals(password1)){
            new GuliException(ResultCodeEnum.LOGIN_PASSWORD_ERROR);
        }

        JwtInfo jwtInfo = new JwtInfo();
        jwtInfo.setAvatar(member.getAvatar());
        jwtInfo.setNickname(member.getNickname());
        jwtInfo.setId(member.getId());
        //创建token
        String token = JwtHelper.createToken(jwtInfo);
        return token;
    }


    @Override
    public String wxlogin(HttpSession session) {
        try {
        String url = "https://open.weixin.qq.com/connect/qrconnect?" +
                "appid=%s" + //wxed9954c01bb89b47
                //http://localhost:8160/api/ucenter/wx/callback8160
                "&redirect_uri=%s" +//回调地址的域名必须和wx平台中配置的授权回调与一致
                "&response_type=code" +
                "&scope=snsapi_login" +
                "&state=%s" + //随机字符串，防止恶意攻击[wx在回调时会将state的值传入]
                "#wechat_redirect";
            String redirectUri = URLEncoder.encode(wxProperties.getRedirectUri(), "utf-8");
            String state = UUID.randomUUID().toString().replace("-", "");
            session.setAttribute("state",state);
            url = String.format(url, wxProperties.getAppId(), redirectUri,state);
            return "redirect:"+url;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    public String wxCallback(String code, String state, HttpSession session) {
        //判断session是否争取
        Object sessionState = (String) session.getAttribute("state");
        if(StringUtils.isEmpty(state)||sessionState==null||!state.equals(sessionState.toString())){
            throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
        }
        try {
        //根据code值获取wx用户的数据: 相当于用户的授权
        //app的身份： appId+appSecurity:
        /*
            # 微信开放平台 appid
            appId: wxed9954c01bb89b47
            # 微信开放平台 appsecret
            appSecret: a7482517235173ddb4083788de60b90e
         */
            String url = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
                    "appid=" + wxProperties.getAppId() +
                    "&secret=" + wxProperties.getAppSecret() +
                    "&code=" + code +
                    "&grant_type=authorization_code";
            HttpClientUtils clientUtils = new HttpClientUtils(url);
            //发起请求
            clientUtils.get();
            //获取相依结果
            String content = clientUtils.getContent();
            System.out.println(content);
            //转成map
            Map map = new Gson().fromJson(content, Map.class);
            if (map.get("errcode")!=null){
                throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
            }
            //获取响应结果信息
            String access_token = map.get("access_token").toString();
            String openid = map.get("openid").toString();
            //通过openid查询数据库用户数据
            LambdaQueryWrapper<Member> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Member::getOpenid,openid);
            Member member = this.baseMapper.selectOne(queryWrapper);
            if (member==null){
                //去微信查询用户数据
                url = "https://api.weixin.qq.com/sns/userinfo?" +
                        "access_token="+ access_token +
                        "&openid="+ openid;
               clientUtils =  new HttpClientUtils(url);
               clientUtils.get();
               content = clientUtils.getContent();
               map = new Gson().fromJson(content,Map.class);
               //封装member对象
                member = new Member();
                member.setOpenid(openid);
                member.setNickname(map.get("nickname").toString());
                int sex = new BigDecimal(map.get("sex").toString()).intValue();
                member.setSex(sex);
                member.setAvatar(map.get("headimgurl").toString());
                this.save(member);
            }
            //创建token返回给页面
            JwtInfo jwtInfo = new JwtInfo();
            jwtInfo.setId(member.getId());
            jwtInfo.setAvatar(member.getAvatar());
            jwtInfo.setNickname(member.getNickname());
            String token = JwtHelper.createToken(jwtInfo);
            return "redirect:http://localhost:3000?token="+token;
        } catch (Exception e) {
            e.printStackTrace();
            throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR,e);
        }
    }

    @Override
    public MemberDto getOrderMember(String memberId) {
        Member member = this.baseMapper.selectById(memberId);
        MemberDto memberDto = new MemberDto();
        BeanUtils.copyProperties(member,memberDto);
        return memberDto;
    }

    @Override
    public Integer getgetRegistNumDay(String day) {
        Integer count = this.count(new QueryWrapper<Member>().eq("DATE(gmt_create)", day));
        return count;
    }
}
